/***************************************************************************
 创建者: hualei
 开始时间: 2018.9.10
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2018.5.8 类的具体实现代码编写

 ***************************************************************************
 *  @file batterymonitor.h
 *  功能: 电池模块的设置和数据获取
 *
 *
 ***************************************************************************/
#ifndef BATTERYMONITOR_H
#define BATTERYMONITOR_H
#include <qvector.h>
#include <qstring.h>
#include <QList>
#include <qmap.h>
#include <QMutex>
#include <QString>
#include <QTimer>
#include "MacroDefine/globalDefine.h"
#include "GeneralDefine.h"


class QSerialPort;
struct SerialPortConfig;
typedef struct _modbus modbus_t;



enum E_BATTERY_VENDOR_ID//CAN电池另外定义 E_VENDOR_ID_LI_TON_WEI=10,
{
    E_BATTERY_VENDOR_ID_NONE=0,
    E_BATTERY_VENDOR_ID_GP07SC_VER01=1,
    E_BATTERY_VENDOR_ID_shangHaiJinQu=2,//上海津瞿
    E_BATTERY_VENDOR_ID_shenZhengAoYouNeng=3,//深圳奥优基能
    E_BATTERY_VENDOR_ID_KAWKER=4,//霍克（深圳讯普）默认id20,9600,8,none
    E_BATTERY_VENDOR_ID_SERVODRIVER_VOLTAGE=5,//从CAN驱动器获取(robitiq, xinsong,KINCO)
    E_BATTERY_VENDOR_ID_PeiChengChuNeng=6,//沛城储能基站ＢＭＳ(上海聿冠　浙江兴海能源）默认id看拨码开关,9600,8,none
//    E_BATTERY_VENDOR_ID_SERVODRIVER_24V=7,//从CAN驱动器获取(robitiq, xinsong)
    E_BATTERY_VENDOR_ID_ShangDongJongGong=8,//山东精工（宏友使用）
    E_BATTERY_VENDOR_ID_SERVODRIVER_VOLUME=9,//从CAN驱动器获取剩余电量(curtis)
    E_BATTERY_VENDOR_ID_AI=10,//从ＡＩ模拟量获取电压．
};

/**
 * @brief The BatteryDevice struct  电池设备
 */
struct BatteryDevice
{
    int batteryDeviceId;        //电池组id
    int batteryVendorId;        //电池厂商Id
};



/**
 * @brief The BatteryPeak struct    电池管理峰值
 */
//struct BatteryPeakConfig
//{
//    int chargeTime;                         //电池充电时间                (单位：min----30----）
//    double chargeVolume;                    //充电相对容量比              (单位：%------70----）
//    double warnningBatteryLeftLightmode;    //警报时电池相对容量比        (单位：%------40----）
//    double goChargeBatteryLeftLightmode;    //需要充电时点此相对容量比    (单位：%------20----）
//    double shutDownBatteryLeftLightmode;    //关机时电池相对容量          (单位：%------5-----）
//};

/**
 * @brief The BatteryMonitor class          电池监控,监控电池的各种状态信息
 */
class BatteryMonitor:public QObject
{
    Q_OBJECT
public:
    /**
     * @brief BatteryMonitor        构造函数
     * @param configFileName        电池配置文件名
     */
    BatteryMonitor(QString configFileName);

public:
    int getBatteryPeakConfig(BatteryPeakConfig &configOut);
    int setBatteryPeakConfig(BatteryPeakConfig configIn);

    int setDebugFlag(int debugFlagIn);
    /**
     * @brief getBatteryInfo        获取电池信息
     * @param batteryInfoOut        电池组信息
     * @return                      success: 1  fail: 0/负数
     */
    int getBatteryInfo(BatteryInformation &batteryInfoOut);

    /**
     * @brief configFileInitalOk    配置文件初始化是否完成
     * @return                      true:finish  false:failed
     */
    bool isInitalOk();

    /**
     * @brief setChargeTime         设置电池充电时间
     * @param chargeTimeIn          具体充电时间数值
     * @return                      success: 1  fail: -1
     */
    int setChargeTime(double chargeTimeIn);

    /**
     * @brief setChargeVolume       设置充电容量
     * @param chargeVolumeIn        具体充电容量
     * @return                      success: 1  fail: -1
     */
    int setChargeVolume(double chargeVolumeIn);

    /**
     * @brief setWarnningBatteryLeftLightmode   设置电池警报模式的电池剩余容量比
     * @param dateIn                            具体容量比
     * @return                                  success: 1  fail: -1
     */
    int setWarnningBatteryLeftLightmode(double dateIn);

    /**
     * @brief setGoChargeBatteryLeftLightmode   设置充电模块
     * @param dateIn                            电池充电容量比
     * @return                                  success: 1  fail: -1
     */
    int setGoChargeBatteryLeftLightmode(double dateIn);

    /**
     * @brief getBatteryStatus  获取电池组状态
     * @param statusOut         状态信息
     * @return                  success: 1
     */
    int getBatteryStatus(E_BATTERY_STATUS &statusOut);
    int getShutdownDelaySeconds();

private:
    int writeConfigFile(QString configFilePath, BatteryPeakConfig configIn);
    /**
     * @brief getBatteryTempture  获取电池组内部温度
     * @param temptureOut         温度信息
     * @return                    success: 1  fail: -1
     */
    int getBatteryTempture(double &temptureOut);//摄氏度

    /**
     * @brief getBatteryTempture    获取电池组某节内部温度
     * @param batteryModuleId       电池ID
     * @param temptureOut           温度信息
     * @return                      success: 1  fail: -1
     */
    int getBatteryTempture(int batteryModuleId,double &temptureOut);//摄氏度

    /**
     * @brief getBatterySumVoltage      获取电池总电压
     * @param voltageOut                电压信息
     * @return                          success: 1  fail: -1
     */
    int getBatterySumVoltage(double &voltageOut);//mV

    /**
     * @brief getBatterySumVoltage      获取电池组某节电池电压
     * @param batteryModuleId           电池ID
     * @param voltageOut                电压信息
     * @return                          success: 1  fail: -1
     */
    int getBatterySumVoltage(int batteryModuleId,double &voltageOut);//mV

    /**
     * @brief getBatteryCurrentCurrency     获取电池组当前电流
     * @param currencyOut                   当前电流信息
     * @return                              success: 1  fail: -1
     */
    int getBatteryCurrentCurrency(double &currencyOut);//mA

    /**
     * @brief getBatteryCurrentCurrency     获取电池组某节电池的当前电流
     * @param batteryModuleId               电池ID
     * @param currencyOut                   当前电流信息
     * @return                              success: 1  fail: -1
     */
    int getBatteryCurrentCurrency(int batteryModuleId,double &currencyOut);//mA

    /**
     * @brief getBatteryLeftLightmodRatio   获取电池组剩余容量百分比
     * @param ratioOut                      剩余容量百分比
     * @return                              success: 1  fail: -1
     */
    int getBatteryLeftLightmodRatio(double &ratioOut);//%

    /**
     * @brief getBatteryLeftLightmodRatio   获取电池组某节电池剩余容量百分比
     * @param batteryModuleId               电池ID编号
     * @param ratioOut                      剩余容量百分比
     * @return                              success: 1  fail: -1
     */
    int getBatteryLeftLightmodRatio(int batteryModuleId,double &ratioOut);//%

    /**
     * @brief getBatteryLeftLightmodVolume      获取电池组剩余容量
     * @param volumeOut                         剩余容量数值
     * @return                                  success: 1  fail: -1
     */
    int getBatteryLeftLightmodVolume(double &volumeOut);//unit is mAh

    /**
     * @brief getBatteryLeftLightmodVolume      获取电池组某节剩余容量
     * @param batteryModuleId                   电池ID编号
     * @param volumeOut                         剩余容量
     * @return                                  success: 1  fail: -1
     */
    int getBatteryLeftLightmodVolume(int batteryModuleId,double &volumeOut);//unit is mAh

    /**
     * @brief getBatteryCycleNumber             获取电池组充电次数
     * @param cycleNumberOut                    充电次数
     * @return                                  success: 1  fail: -1
     */
    int getBatteryCycleNumber(double &cycleNumberOut);

    /**
     * @brief getBatteryCycleNumber             获取电池组某节电池充电次数
     * @param batteryModuleId                   电池ID编号
     * @param cycleNumberOut                    充电次数
     * @return                                  success: 1  fail: -1
     */
    int getBatteryCycleNumber(int batteryModuleId,double &cycleNumberOut);

    /**
     * @brief getBatteryDesignVolume              获取电池组设计容量
     * @param designVolumeOut                     设计容量数值
     * @return                                    success: 1  fail: -1
     */
    int getBatteryDesignVolume(double &designVolumeOut);//unit is mAh

    /**
     * @brief getBatteryDesignVolume               获取电池组某节电池的设计容量
     * @param batteryModuleId                      电池ID编号
     * @param designVolumeOut                      设计容量数值
     * @return                                     success: 1  fail: -1
     */
    int getBatteryDesignVolume(int batteryModuleId,double &designVolumeOut);//unit is mAh

    /**
     * @brief getBatteryOnePartVoltage             获取电池组各节电池电压
     * @param batteryModuleId                      电池模块ID编号
     * @param voltageListOut                       保存各节电池电压容器
     * @return                                     success: 1  fail: -1
     */
    int getBatteryOnePartVoltage(int batteryModuleId, std::vector<double> &voltageListOut);//unit is mAh

private:

    /**
     * @brief batteryMonitorLoop        电池状态监控循环
     * @return                          success: 1
     */
    int batteryMonitorLoop();

    /**
     * @brief initialBatteryByConfigFile        初始化电池模块配置文件
     * @param configFileName                    电池配置文件名
     * @return                                  success: 1  fail: -1
     */
    int initialBatteryByConfigFile(QString configFileName);

    int initialModbusMaster(SerialPortConfig *serialPortConfigIn,int aliasIdIn);

    /**
     * @brief initalSerialPort                  初始化串行端口
     * @return                                  success: 1  fail: -1
     */
    int initalSerialPort();

    /**
     * @brief sendGetValueCommand               发送获取数据命令
     * @param batteryModuleId                   接收命令设备ID编号
     * @return                                  success: 1
     */
    int sendGetValueCommand(int batteryModuleId);

    /**
     * @brief GP07SC_VER01_Command              获取GP07SC_VER01型号电池获取数据命令
     * @param sendCommand                       命令
     */
    void GP07SC_VER01_Command(QByteArray &sendCommand);

    /**
     * @brief shangHaiJinQu_Command             获取shangHaiJinQu型号电池获取数据命令
     * @param sendCommand                       命令
     */
    void shangHaiJinQu_Command(QByteArray &sendCommand);

    void shenZhengAoYouNeng_Command(QByteArray &sendCommand);
    void sendRequestCommand_PeiChengChuNeng(QByteArray &sendCommand);
    void sendRequestCommand_ShangDongJingGong(QByteArray &sendCommand);

    /**
     * @brief GP07SC_VER01_ReceiveData          GP07SC_VER01型号电池获取数据
     * @param dataIn                            电池数据
     * @return                                  success: 1  fail: -1
     */
    int GP07SC_VER01_ReceiveData(QByteArray &dataIn);

    /**
     * @brief shangHaiJinQu_ReceiveData         shangHaiJinQu型号电池获取数据
     * @param dataIn                            电池数据
     * @return                                  success: 1  fail: -1
     */
    int shangHaiJinQu_ReceiveData(QByteArray &dataIn);

    int shangHaiJinQu_bufferCheck(QByteArray &dataIn);

    int shenZhengAoYouNeng_ReceiveData(QByteArray &dataIn);

    int shenZhengAoYouNeng_bufferCheck(QByteArray &dataIn);
    int bufferCheck_PeiChengChuNeng(QByteArray &dataIn);
    int bufferCheck_ShangDongJingGong(QByteArray &dataIn);
    int receiveData_PeiChengChuNeng(QByteArray &dataIn);
    int receiveData_ShangDongJingGong(QByteArray &dataIn);
    int getVoltage_ShangDongJingGong(QByteArray &dataIn);
    int getStatus_ShangDongJingGong(QByteArray &dataIn);
    int getVolume_ShangDongJingGong(QByteArray &dataIn);

    int updateBatteryStatus(double lightModeRatioIn,E_BATTERY_STATUS &statusOut);

    unsigned char valueToAscii(unsigned char bHex);//数值转换为ascii码

    unsigned char asciiToValue(unsigned char bChar);//ascii码转换为数值
    int modbusBatteryCommunicateLoop(BatteryInformation &batteryInformationOut);
    int modbusBatteryCommunicateLoop_kawker(BatteryInformation &batteryInformationOut);

private slots:
    // 接收数据槽函数
    int receiveData();

    /**
     * @brief timeOut_slot  定时响应槽函数
     */
    void timeOut_slot();

private:
    QString configFilePath;

    /**
     * @brief requestCount              请求数量
     */
    int requestCount;
    /**
     * @brief batteryCommandVec         电池通讯命令
     */
    QVector <int> batteryCommandVec;

    /**
     * @brief batteryInformationMap     电池模块信息容器
     */
    QMap <int, BatteryInformation> batteryInformationMap;

    /**
     * @brief batteryDeviceMap          电池模块设备信息容器(电池组ID / 电池厂商ID)
     */
    QMap <int, BatteryDevice> batteryDeviceMap;

    /**
     * @brief itBatteryDeviceMap        电池模块设备信息容器迭代器对象
     */
    QMap <int, BatteryDevice>::Iterator itBatteryDeviceMap;

    /**
     * @brief itCommandVec  电池通讯命令器迭代器对象
     */
    QVector <int>::Iterator itCommandVec;

    /**
     * @brief isInitialOkStatus         配置文件初始化状态
     */
    bool isInitialOkStatus;

    /**
     * @brief serialPort_device                串口对象
     */
    QSerialPort *serialPort_device;

    /**
     * @brief serialPortConfig          串口配置對象
     */
    SerialPortConfig *serialPortConfig;

    /**
     * @brief batteryPeak               电池管理峰值对象
     */
    BatteryPeakConfig *batteryPeak;

    /**
     * @brief mutex                     mutex锁对象
     */
    QMutex mutex;

    /**
     * @brief timer                     定时器
     */
    QTimer timer;

    /**
     * @brief batteryConfigFilePath     电池配置文件路径
     */
    QString batteryConfigFilePath;

    E_BATTERY_STATUS batteryStatus;
    int isUseBattery;
    int debugFlag;
    int batteryBusType;//0 serial, 1 can，　２ modbus-rtu协议
    int batteryBusAlias;//can device alias id,modbus id.
    BatteryInformation batteryInformation_can;//can专用
    BatteryInformation batteryInformation_modbus;//modbus专用
    modbus_t* modbusMaster;//modbus协议使用
    int shutdownDelaySeconds;
    double minBatteryVoltage;
    double maxBatteryVoltage;
};

#endif // BATTERYMONITOR_H
